package com.arcsoft.crud.limitNumber.base;

import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public abstract class BenchmarkBase {

	protected int threadCount;
	protected long loopCount;

	protected CountDownLatch startLock;
	protected CountDownLatch finishLock;

	public BenchmarkBase(int threadCount, long loopCount) {
		this.threadCount = threadCount;
		this.loopCount = loopCount;

		startLock = new CountDownLatch(threadCount);
		finishLock = new CountDownLatch(threadCount);
	}

	public void run() throws Exception {
		onStart();

		//start threads
		ExecutorService threadPool = Executors.newFixedThreadPool(threadCount);
		try {
			for (int i = 0; i < threadCount; i++) {//20个客户端，每个客户端执行5w次incr操作
				threadPool.execute(getTask(i));
			}

			//wait for all threads ready
			startLock.await();

			//print start message
			String className = this.getClass().getSimpleName();
			long invokeTimes = threadCount * loopCount;
			System.out.printf("%s start.%d threads with %,d loops, totally %,d requests will be invoked.\n", className,
					threadCount, loopCount, invokeTimes);
			Date startTime = new Date();

			//wait for all threads finish
			finishLock.await();

			//print summary message
			long timeInMills = new Date().getTime() - startTime.getTime();
			long tps = invokeTimes * 1000 / timeInMills;

			System.out.printf("%s finish.\n%d thread spend %,d ms for %,d requests, TPS is %,d.\n", className,
					threadCount, timeInMills, invokeTimes, tps);
		} finally {
			threadPool.shutdownNow();
			onFinish();
		}
	}

	/**
	 * Override to do some global data prepare job.
	 */
	protected void onStart() {
	}

	/**
	 * Override to do some global data cleanup and verify job.
	 */
	protected void onFinish() {
	}

	/**
	 * Return a new benchmark task. 
	 */
	abstract protected Runnable getTask(int threadIndex);


	/*// 模拟了100米赛跑，10名选手已经准备就绪，只等裁判一声令下。当所有人都到达终点时，比赛结束。
    public static void main(String[] args) throws InterruptedException {

        // 开始的倒数锁 
        final CountDownLatch begin = new CountDownLatch(10);  

        // 结束的倒数锁 
        final CountDownLatch end = new CountDownLatch(10);  

        // 十名选手 
        final ExecutorService exec = Executors.newFixedThreadPool(10);  

        for (int index = 0; index < 10; index++) {
            final int NO = index + 1;  
            Runnable run = new Runnable() {
                public void run() {  
                    try {  
                        // 如果当前计数为零，则此方法立即返回。
                        // 等待
                        begin.countDown();
                        Thread.sleep((long) (Math.random() * 10000));  
                        System.out.println("No." + NO + " arrived");  
                    } catch (InterruptedException e) {  
                    } finally {  
                        // 每个选手到达终点时，end就减一
                        end.countDown();
                    }  
                }  
            };  
            exec.submit(run);
        }  
        System.out.println("Game Start");  
        // begin减一，开始游戏
        begin.await();  
        // 等待end变为0，即所有选手到达终点
        end.await();  
        System.out.println("Game Over");  
        exec.shutdown();  
    }*/
}
